use diesel::prelude::*;
use diesel::PgConnection;

use crate::models::person_role::PersonRole;
use crate::models::{
  person::Person,
  role::{NewRole, Role},
};
use crate::schema::roles;

pub struct RoleMapper;

impl RoleMapper {
  pub fn find_by_person(
    conn: &mut PgConnection,
    person: &Person,
  ) -> QueryResult<Vec<Role>> {
    let person_roles = PersonRole::belonging_to(person).get_results(conn)?;

    let ids = person_roles
      .iter()
      .map(|pr: &PersonRole| pr.role_id)
      .collect();

    Self::find_by_ids(conn, ids)
  }

  pub fn find_by_ids(
    conn: &mut PgConnection,
    ids: Vec<i32>,
  ) -> QueryResult<Vec<Role>> {
    roles::table.filter(roles::id.eq_any(ids)).get_results(conn)
  }

  pub fn find_by_code(
    conn: &mut PgConnection,
    code: &str,
  ) -> QueryResult<Role> {
    roles::table
      .filter(roles::code.eq(code))
      .get_result::<Role>(conn)
  }

  pub fn create(
    conn: &mut PgConnection,
    new_role: NewRole,
  ) -> QueryResult<Role> {
    diesel::insert_into(roles::table)
      .values(new_role)
      .get_result(conn)
  }
}
